/******************************************************************
 * Created by: Goh Chee Hong                                       
 * Date of Creation: 1/1/2009

 * Status: Optimized and Finished
 *                                                                
 * Description: Receive a library file
 ******************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Pbdms.Common.Interfaces;
using Pbdms.NetworkDealer;
using Pbdms.Common.DataObject;
using System.IO;
namespace Pbdms.BusinessLogic.FileTransfer
{
    public class LibraryTransferReceiverGui:FileTransferGui
    {
        /// <summary>
        /// library item id
        /// </summary>
        private string itemID;
        /// <summary>
        /// file type   1 is file 2 is review file
        /// </summary>
        private string fileType;

        /// <summary>
        /// destination IP address
        /// </summary>
        private string IPAddress;



        private Thread thTransfer = null;
        public LibraryTransferReceiverGui()
        {

        }
        public LibraryTransferReceiverGui(string itemID, string fileType, System.IO.FileInfo fileInfo, Common.SharedVariables.FriendsControl friendsControl, string IP, Network.NetworkController networkController)
        : base()
        {
            this.fileInfo = fileInfo;
           
            this.itemID = itemID;
            this.fileType = fileType;
           
            this.IPAddress = IP;

            Buddy buddy = friendsControl.getAFriendByIP(IP);
            if (buddy == null)
            {
                this.keyID = "unknown";
                this.friendName = "unknown";
            }
            else
            {
                this.keyID = buddy.KeyID;
                this.friendName = buddy.Name;
            }
            this.networkController = networkController;
            this.lblDoc.Text = fileInfo.Name;
            this.lblUser.Text = friendName;
        }
        public string FileType
        {
            get { return fileType; }
        }
        public override void start()
        {
            thTransfer = new Thread(new ThreadStart(receive));
            thTransfer.IsBackground = true;
            thTransfer.Start();
        }
        public void receive()
        {
            System.IO.FileStream fout = null;
            authTcpClient = new AuthTcpClient(IPAddress, NetworkDealer.NetworkDealer.LISTEN_PORT,keyID, networkController.keyControl, networkController.publicKeyControl, networkController.friendsControl);
            try
            {

                authTcpClient.Connect();
                if (authTcpClient.IsAuthenticated() == false)
                {
                    if (keyID != null&& !keyID.Equals("unknown"))
                    {
                        throw new Exception("Not authenticated");
                    }
                }
                NetworkMessage message = new NetworkMessage();
                message.TypeOfMessage = NetworkDealer.NetworkDealer.DOWNLOAD_REQUEST;
                //item id, type;
                message.MessageContent = itemID + "," + fileType;
                authTcpClient.sendMessage(message);
                displayStatus("waiting for transfer");
                ///receive reply
                message = authTcpClient.receiveMessage();
                if (message.TypeOfMessage == NetworkDealer.NetworkDealer.DOWNLOAD_REQUEST_GRANTED)
                {
                    //start receive
                    fout = new FileStream(fileInfo.FullName, FileMode.Create, FileAccess.Write);
                    displayStatus("Download request granted");
                    Thread.Sleep(500);

                    //starts receiving
                    long rby = 0;
                    int perc = 0;

                    int filesize = int.Parse(message.MessageContent);

                    string currentDownload = Common.Global.GetFileSize(rby);
                    string totalString = Common.Global.GetFileSize(filesize);
                    displayStatus("downloading " + currentDownload + " of " + totalString);
                    int before = 0;
                    while (rby < filesize)
                    {
                        byte[] buffer = null;
                        //Read from the Network Stream
                        try
                        {
                            ///measure the length of the block
                            int length = 1024;
                            if (rby + 1024 > filesize)
                            {
                                length = (int)(filesize - rby);
                            }

                            //receive the bytes
                            buffer = authTcpClient.receiveBytes();
                            fout.Write(buffer, 0, buffer.Length);
                            rby = rby + buffer.Length;
                            perc = (int)(((double)rby / (double)filesize) * 100.00);
                            if (before != perc)
                            {
                                displayProgress(perc.ToString());
                                currentDownload = Common.Global.GetFileSize(rby);
                                totalString = Common.Global.GetFileSize(filesize);
                                Thread.Sleep(100);
                            }
                            displayStatus("downloading " + currentDownload + " of " + totalString);
                            Thread.Sleep(100);
                            before = perc;
                        }
                        catch
                        {
                            break;
                        }
                    }

                    //complete transferred
                    if (rby == filesize)
                    {
                        //no error
                        finished = true;
                        displayStatus("Finished downloading");
                        FinishedEvent(this);
                    }
                    else
                    {
                        displayStatus("The connection is disconnected");
                        fout.Close();
                        File.Delete(fileInfo.FullName);
                    }
                    //signal it is finished
                    Finished("");
                    fout.Close();




                }
                else
                {
                    displayStatus("Download request rejected");
                }
                Finished("");
            }
            catch
            {
                try
                {
                    displayStatus("An unknown error occurred");
                    Finished("");
                }
                catch
                {

                }
            }
            finally
            {
                if (fout != null)
                {
                    fout.Close();
                }
                authTcpClient.Close();
                finished = true;
            }

        }
    }
}
